/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.thingsgrid.device.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mongodb.BasicDBObject;
import com.mysql.cj.x.protobuf.MysqlxDatatypes;
import com.thingsgrid.device.dto.DeviceDTO;
import com.thingsgrid.device.entity.*;
import com.thingsgrid.device.service.IProductService;
import com.thingsgrid.device.service.ITopicService;
import com.thingsgrid.device.vo.ProductVO;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.poi.ss.formula.functions.Count;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.LookupOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.querydsl.QuerydslUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.Array;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 *  服务实现类
 *
 * @author BladeX
 * @since 2019-08-19
 */
@ComponentScan("com.springblade.device.feign")
@Service
public class ProductServiceImpl implements IProductService {
	@Autowired
	private ITopicService topicService;
	@Autowired
	private MongoTemplate mongoTemplate;

	/**
	 * 产品新增
	 */
	@Override
	public boolean saveProduct(Product product) {
		String str = UUID.randomUUID().toString().replace("-", "").substring(0, 12);
		String productId = UUID.randomUUID().toString();
		product.setProductId(productId);
		product.setProductKey(str);
		//查询产品类型
		ProductType oneProductType = this.findOneProductType(product.getProductTypeId());
		product.setProductType(oneProductType.getProductType());
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String format = df.format(new Date());
		product.setCreateTime(format);
		product.setVersion(1);
		product.setDeviceIcon("1");
		product.setDeviceLinkStrong(1);
		product.setDeviceLinkColor("#000000");
		product.setIsPublish("0");
		product.setDeviceCount(0);
		Product save = mongoTemplate.save(product);
		if(save != null){
			return true;
		}else{
			return false;
		}
	}


	@Override
	public ProductType findOneProductType(String productTypeId) {
		//查询产品类型
		Query query = new Query();
		query.addCriteria(Criteria.where("productTypeId").is(productTypeId));
		return mongoTemplate.findOne(query, ProductType.class, "product_type");
	}

	/**
	 * 说明：产品发布
	 * @author 陈学栋
	 * @since 2019/10/11 16:23
	 */
    @Override
    public long productPublish(String productId) {
        Query query = new Query();
        Update update = new Update();
        query.addCriteria(Criteria.where("productId").is(productId));
        Product product = mongoTemplate.findOne(query, Product.class, "product");
        if(product.getIsPublish().equals("0")){
            update.set("isPublish","1");
            return mongoTemplate.updateFirst(query, update, Product.class, "product").getModifiedCount();
        }else{
            update.set("isPublish","0");
            return mongoTemplate.updateFirst(query,update,Product.class,"product").getModifiedCount();
        }
    }

	@Override
	public boolean addProductTopic(String productId, Topic[] topic) {
		Query query = new Query();
		query.addCriteria(Criteria.where("productId").is(productId));
		Update update = new Update();
		ArrayList<Object> topicClassArraysList = new ArrayList<>();
		Product product = mongoTemplate.findOne(query, Product.class, "product");
		List<Topic> topicClass = product.getTopicClass();
		for (Topic t:topicClass){
			topicClassArraysList.add(t);
		}
		for (int i = 0; i < topic.length; i++){
			topicClassArraysList.add(i,topic[i]);
		}
		update.set("topicClass",topicClassArraysList);
		long modifiedCount = mongoTemplate.upsert(query, update, Product.class, "product").getModifiedCount();
		if(modifiedCount > 0){
			return true;
		}else{
			return false;
		}
	}

	/**
	 * 说明：产品修改
	 * @author 陈学栋
	 * @since 2019/10/11 16:09
	 */
	@Override
	public boolean updateProduct(Product product) {
		Query query = new Query();
		query.addCriteria(Criteria.where("productId").is(product.getProductId()));
		Update update = new Update();
		update.set("productName", product.getProductName());
		update.set("product_type_id", product.getProductTypeId());
		ProductType oneProductType = this.findOneProductType(product.getProductTypeId());
		update.set("ProductType",oneProductType.getProductType());
		//update.set("networkProtocol",product.getNetworkProtocol());
		//update.set("dataFormat",product.getDataFormat());
		update.set("productDescribe",product.getProductDescribe());
        long modifiedCount = mongoTemplate.updateFirst(query, update, Product.class, "product").getModifiedCount();
        if(modifiedCount != 0){
            return true;
        }else{
            return false;
        }
    }
	/**
	 * 说明：删除产品的Topic
	 * @author 陈学栋
	 * @since 2019/10/14 16:26
	 */
	@Override
	public boolean removeProductTopic(String productId, Topic topic) {
		//通过Id查询一条Product
		Product product = this.findProductById(productId);
		List<Topic> topicClass = product.getTopicClass();
		ArrayList<Object> topicList = new ArrayList<>();
		Query query = new Query();
		Update update = new Update();

		query.addCriteria(Criteria.where("productId").is(productId));
		for(Topic t:topicClass){
			if(t.getTopicClassName().equals(topic.getTopicClassName())){
				continue;
			}else{
				topicList.add(t);
			}
		}
		update.set("topicClass",topicList);
		long modifiedCount = mongoTemplate.upsert(query, update, Product.class, "product").getModifiedCount();
		if(modifiedCount > 0){
			return true;
		}else{
			return false;
		}
	}

	/**
	 * 根据Id查产品信息
	 */
	@Override
	public Product findProductById(String productId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("productId").is(productId));
		Product product = mongoTemplate.findOne(query,Product.class,"product");
		if(product.getIsPublish().equals("1")){
			product.setIsPublish("已发布");
		}else{
			product.setIsPublish("未发布");
		}
		return product;
	}
	/**
	 * 查找所有产品信息
	 */
	@Override
	public List<Product> findAll() {
		System.out.println(RandomStringUtils.random(6,"123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
		return mongoTemplate.findAll(Product.class);
	}

	/**
	 * 分页查找所有产品信息
	 * @return
	 */
	@Override
	public HashMap<String, Object> findAll(Integer current, Integer size, String productName, String productTypeId, String startTime,
                                           String endTime, Integer isPublish) {
		Query query = new Query().skip((current - 1) * size).limit(size);
		HashMap<String, Object> map = new HashMap<>();
		List<Product> list = mongoTemplate.find(query, Product.class, "product");
		if (list.size() > 0) {
			for (Product productList : list) {
				System.out.println(productList);
				if(null!=productList.getIsPublish()){
					if ("1".equals(productList.getIsPublish())) {
						productList.setIsPublish("已发布");
					} else {
						productList.setIsPublish("未发布");
					}
				}
				long deviceCount = mongoTemplate.count(new Query(Criteria.where("productId").is(productList.getProductId())), Device.class,"device");
				productList.setDeviceCount(deviceCount);
			}
		}
		long productCount = mongoTemplate.count(query, Product.class, "product");
		map.put("productList", list);
		map.put("total", productCount);
		return map;

//		if(productName == null || productName.equals("") && productTypeId == null || productTypeId.equals("") &&startTime == null && startTime.equals("")
//				&& endTime == null && endTime.equals("") && isPublish == null && isPublish.equals("")){
//			List<Product> list = mongoTemplate.find(query, Product.class, "product");
//			long productCount = mongoTemplate.count(query, Product.class, "product");
//			map.put("productList", list);
//			map.put("total", productCount);
//			return map;
//        }else {
//			query.addCriteria(Criteria.where("createTime").gte(startTime+" 00:00:00").lte(endTime+" 00:00:00").and("productName").is(productName)
//					.and("isPublish").is(isPublish).and("productTyptId").is(productTypeId));
//			List<Product> list = mongoTemplate.find(query, Product.class, "product");
//			long productCount = mongoTemplate.count(query, Product.class,"product");
//			map.put("productList",list);
//			map.put("total",productCount);
//			return map;
//        }




//		if(productName == null || "".equals(productName) && startTime == null && "".equals(startTime)
//				&& endTime == null && "".equals(endTime) && isPublish == null && "".equals(isPublish)){
//			List<Product> list = mongoTemplate.find(query, Product.class, "product");
//			long productCount = mongoTemplate.count(query, Product.class,"product");
//			map.put("productList",list);
//			map.put("total",productCount);
//			return map;
//		}else if(productName != null && !"".equals(productName) && startTime == null || "".equals(startTime)
//				&& endTime == null || "".equals(endTime) && isPublish == null || "".equals(isPublish)){
//			List<Product> list = mongoTemplate.find(query.addCriteria(Criteria.where("productName").is(productName)), Product.class, "product");
//			long productCount = mongoTemplate.count(query, Product.class,"product");
//			map.put("productList",list);
//			map.put("total",productCount);
//			return map;
//		}else if(productName == null || "".equals(productName) && startTime != null || !"".equals(startTime)
//				&& endTime != null || !"".equals(endTime) && isPublish == null || "".equals(isPublish)){
//			List<Product> list = mongoTemplate.find(query.addCriteria(Criteria.where("createTime").gte(startTime).lte(endTime)), Product.class, "product");
//			long productCount = mongoTemplate.count(query, Product.class,"product");
//			map.put("productList",list);
//			map.put("total",productCount);
//			return map;
//		}else{
//			List<Product> list = mongoTemplate.find(query.addCriteria(Criteria.where("isPublish").is(isPublish)), Product.class, "product");
//			long productCount = mongoTemplate.count(query, Product.class,"product");
//			map.put("productList",list);
//			map.put("total",productCount);
//			return map;
//		}








//        Query query = new Query();
//		HashMap<String, Object> map = new HashMap<>();
//		Pageable pageable = new PageRequest(pageIndex-1, pageSize);
//		//Query querypage = query.with(pageable);
//		if(productName == null && "".equals(productName) && startTime == null && "".equals(startTime) && endTime == null && "".equals(endTime)){
//			if(isPublish != null && "".equals(isPublish)){
//				Query query1 = query.with(pageable).addCriteria(Criteria.where("isPublish").is(isPublish));
//				List<Product> list = mongoTemplate.find(query1, Product.class,"product");
//				long productCount = mongoTemplate.count(query1, Product.class,"product");
//				map.put("productList",list);
//				map.put("total",productCount);
//				return map;
//			}else{
//				List<Product> list = mongoTemplate.find(new Query(), Product.class,"product");
//				long productCount = mongoTemplate.count(new Query(), Product.class,"product");
//				map.put("productList",list);
//				map.put("total",productCount);
//				return map;
//			}
//
//        } else if(productName != null &&  "".equals(productName)){
//			Query query1 = query.with(pageable).addCriteria(Criteria.where("productName").is(productName).and("isPublish").is(isPublish));
//            List<Product> list = mongoTemplate.find(query1, Product.class,"product");
//            long productCount = mongoTemplate.count(query1, Product.class,"product");
//            map.put("productList",list);
//            map.put("total",productCount);
//            return map;
//        }else if(startTime != null && "".equals(startTime) && endTime != null && "".equals(endTime)){
//			Query query1 = query.with(pageable).addCriteria(Criteria.where("isPublish").is(isPublish).gte("createTime").gte(startTime).lte(endTime));
//            List<Product> list = mongoTemplate.find(query1, Product.class,"product");
//            long productCount = mongoTemplate.count(query1, Product.class,"product");
//            map.put("productList",list);
//            map.put("total",productCount);
//            return map;
//        }
//		return null;
	}




	/**
	 * 添加topicItem
	 * @param productId
	 * @return
	 */
//	@Override
//	public void addTopicItem(String productId, String topicClassName) {
//		Topic topic  = topicService.findTopicByName(topicClassName);
//		Query query = Query.query(Criteria.where("productId").is(productId));
//		Update update = new Update();
//		update.addToSet("topicItems", topic);
//		mongoTemplate.upsert(query, update, Product.class);
//
//	}

//	@Override
//	public void addSubscribeTopicItems(String productId, String topicClassName) {
//		Product product = this.findProductById(productId);
//		Topic topic= null;
//		List<Topic> topicItem = product.getTopicItems();
//		for (Topic topicItem1 : topicItem) {
//			if (topicClassName.equals(topicItem1.getTopicClassName())) {
//				topic = topicService.findTopicByName(topicClassName);
//				break;
//			}
//		}
//		//Topic topic  = topicService.findTopicByName(topicClassName);
//		Query query = Query.query(Criteria.where("productId").is(productId));
//		Update update = new Update();
//		if(topic!=null) {
//			update.addToSet("subscribeTopicItems", topic);
//			mongoTemplate.upsert(query, update, Product.class);
//
//		}
//	}

	//添加Topic
	@Override
	public void addTopicItem(String productId, String topicId) {
		Topic topic  = topicService.findTopicById(topicId);
		Query query = Query.query(Criteria.where("productId").is(productId));
		Update update = new Update();
		update.addToSet("topicItems", topic);
		mongoTemplate.upsert(query, update, Product.class);

	}
	@Override
	public void removeTopicItem(String productId, String topicId) {
		//Topic topic  = topicService.findTopicById(topicId);
		Query query = Query.query(Criteria.where("productId").is(productId));
		BasicDBObject s = new BasicDBObject();
		s.put("topicId", topicId);
		Update update = new Update();
		update.pull("topicItems", s);
		mongoTemplate.updateFirst(query, update, Product.class);

	}
	@Override
	public void removeSubscribeTopicItem(String productId, String topicId) {
		Query query = Query.query(Criteria.where("productId").is(productId));
		BasicDBObject s = new BasicDBObject();
		s.put("topicId", topicId);
		Update update = new Update();
		update.pull("subscribeTopicItems", s);
		mongoTemplate.updateFirst(query, update, Product.class);

	}
	@Override
	public void addSubscribeTopicItem(String productId, String topicId) {
		Product product = this.findProductById(productId);
		Topic topic= null;
		List<Topic> topicItem = product.getTopicItems();
		for (Topic topicItem1 : topicItem) {
			if (topicId.equals(topicItem1.getTopicId())) {
				topic = topicService.findTopicById(topicId);
				break;
			}
		}
		//Topic topic  = topicService.findTopicByName(topicClassName);
		Query query = Query.query(Criteria.where("productId").is(productId));
		Update update = new Update();
		if(topic!=null) {
			update.addToSet("subscribeTopicItems", topic);
			mongoTemplate.upsert(query, update, Product.class);

		}
	}

	@Override
	public List<Topic> listTopicItems(String productId) {
		List<Topic> list =null;
		Product product = this.findProductById(productId);
		if(product!=null){
			list = product.getTopicItems();
		}
		return list;
	}

	@Override
	public List<Topic> listSubscribeTopicItems(String productId) {
		Product product = this.findProductById(productId);
		List<Topic> list = product.getSubscribeTopicItems();
		return list;
	}

	@Override
	public void addPhysical(String productId, String physicalModelId) {
		Query query = new Query();
		Criteria criteria = new Criteria();
		query.addCriteria(criteria.where("_id").is(productId));
		/*Product one = mongoTemplate.findOne(query,Product.class);
		one.setPhysicalModelId(physicalModelId);*/
		Update update = new Update();
		update.set("physicalModelId", physicalModelId);
		mongoTemplate.upsert(query,update,Product.class);
	}
	@Override
	public void removePhysical(String productId, String physicalModelId) {
		Query query = new Query();
		Criteria criteria = new Criteria();
		query.addCriteria(criteria.where("_id").is(productId));
		/*Product one = mongoTemplate.findOne(query,Product.class);
		one.setPhysicalModelId(physicalModelId);*/
		Update update = new Update();
		update.set("physicalModelId", null);
		mongoTemplate.upsert(query,update,Product.class);
	}
	@Override
	public String  getPhysicalId(String productId) {
		Query query = new Query();
		Criteria criteria = new Criteria();
		query.addCriteria(criteria.where("_id").is(productId));
		Product one = mongoTemplate.findOne(query,Product.class);
		String physicalModelId = one.getPhysicalModelId();
		return physicalModelId;
	}

	@Override
	public List<Function> getFunctionbyPhysicalModelId(String physicalModelId) {
		//List<Function> functionList = client.getFunctionByPhysicalModelId(physicalModelId);
		List<Function>functionList = new ArrayList<Function>();
		Function function=new Function();
		function.setFuctionType("属性");
		function.setFuctionName("电流");
		function.setDataType("浮点");
		functionList.add(function);
		return functionList;
	}

	@Override
	public List<Product> selectByCondition(String productName, String productType, Timestamp beginTime, Timestamp endTime,
										   Integer isPublish) {

		//List<Criteria> criteriaList = new ArrayList<>();
		//Criteria[] criteriaArray = {};
		Query query = new Query();
		Criteria criteria = new Criteria();
		//判断产品名是否为空
		if (productName != null && !productName.trim().equals("")) {
			query.addCriteria(Criteria.where("productName").is(productName));

		}
		if (productType != null && !productType.trim().equals("")) {
			query.addCriteria(Criteria.where("productType").is(productType));
		}
		// 判断时间是否为空
		if (beginTime != null && endTime != null) {
			// 添加大于开始时间小于结束时间的条件
			query.addCriteria(Criteria.where("createTime").gte(beginTime).lte(endTime));

		} else {
			// 其中一个为空 分别进行判断
			if (beginTime != null) {
				query.addCriteria(Criteria.where("time").gte(beginTime));
			}
			if (endTime != null) {
				query.addCriteria(Criteria.where("time").gte(endTime));
			}
		}
// 添加状态为1条件
		if (isPublish != null) {
			query.addCriteria(Criteria.where("isPublish").is(isPublish));
			//criteriaList.add(publish);
		}
		//query.addCriteria(criteria);
		return mongoTemplate.find(query, Product.class);
	}

	@Override
	public Object findProductAndTopic() {
		LookupOperation lookupOperation = LookupOperation.newLookup().
			from("topic").   //关联从表名;
			localField("topicClass").       //主表关联字段;
			foreignField("topicClass").     //从表关联字段
			as("productAndTopic");    //查询结果名

		Aggregation aggregation= Aggregation.newAggregation(lookupOperation);
		List<Map> result = mongoTemplate.aggregate(aggregation,"product", Map.class).getMappedResults();
		return result;
	}

	@Override
	public IPage<ProductVO> selectProductPage(IPage<ProductVO> page, ProductVO product) {
		return null;
	}


	/**
	 *说明：产品发布
	 *@author lilongfei
	 *@since 2019/9/20 15:31
	 */
	@Override
	public long cancelPublishOrDelete(String productId) {
		Query query = Query.query(Criteria.where("productId").is(productId));
		Update update = new Update();
		String publish = mongoTemplate.findOne(query, Product.class, "product").getIsPublish();
		//如果产品是发布状态，改为未发布状态
		if(publish.equals("1")){
			update.set("isPublish","0");
			 return mongoTemplate.updateFirst(query,update,Product.class,"product").getModifiedCount();
		}else{
			//如果产品时未发布状态，就可以直接删除
			 return mongoTemplate.remove(query,Product.class,"product").getDeletedCount();
		}
	}

	@Override
	public List<ProductType> getProductType() {
		List<ProductType> productTypeList = mongoTemplate.find(new Query(), ProductType.class, "product_type");
		return productTypeList;
	}
}